package com.py.custom.tms.application.redis;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;

public class Server {

    private static final String IP = "127.0.0.1";

    private static final int PORT = 9907;

    public static void main(String[] args) throws Exception {
        // 1 nio Socket
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 2 绑定
        InetSocketAddress addr = new InetSocketAddress(IP, PORT);
        serverSocketChannel.bind(addr);

        // 3 设置为非阻塞
        serverSocketChannel.configureBlocking(false);

        // 4 打开一个选择器
        Selector selector = Selector.open();

        // 5 socketChannel注册到选择器中,监听连接事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 具体业务操作
        while (true) {
            // 1 等待3秒，（返回0相当于没有事件）如果没有事件，则跳过
            if (selector.select(3000) == 0) {
                continue;
            }

            // 2 如果有事件（selector.select(3000) > 0）, 获取事件
            Set<SelectionKey> selectionKeys = selector.selectedKeys();

            // 3 遍历事件
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                selectionKey.isConnectable();
                if (selectionKey.isAcceptable()) {
                    // 连接事件
                    // 服务-客户端 连接通道，注意当没有连接当时候，非阻塞下返回null
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    if (Objects.nonNull(socketChannel)) {
                        //设置成非阻塞
                        socketChannel.configureBlocking(false);
                        //把socketChannel注册到selector中，监听读事件，并绑定一个缓冲区
                        socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                    }
                }

                if (selectionKey.isReadable()) {
                    // 如果是读事件
                    //获取通道
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    //获取关联的ByteBuffer
                    ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
                    //打印从客户端获取到的数据
                    int num = socketChannel.read(buffer);
                    buffer.clear();
                    if (num == -1) {
                        socketChannel.close();
                    } else {
                        System.out.println("from 客户端：" + new String(buffer.array()));
                    }
                }
            }
            selectionKeys.clear();
        }
    }
}
